package com.guang.base;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import java.io.Serializable;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class BizServiceImpl<M extends BizMapper<T>, T extends BizEntity> extends ServiceImpl<M, T> implements BizService<T> {

    @Override
    public <E extends IPage<T>> E page(E page, Wrapper<T> queryWrapper) {
        long size = page.getSize();
        if (size < 0) {
            List<T> list = list(queryWrapper);
            IPage<T> result = new Page<>();
            result.setRecords(list);
            result.setPages(1);
            result.setTotal(list == null ? 0 : list.size());
            result.setCurrent(1);
            result.setSize(list == null ? 0 : list.size());
            return (E) result;
        }
        //处理sql优化，如果存在lastId 则不进行分页count，直接查询列表
        boolean searchCount = page.searchCount();
        String lastId = page.countId();
        if(!searchCount){
            List<Long> idList = null;
            if(queryWrapper instanceof LambdaQueryWrapper){
                LambdaQueryWrapper<T> lw = (LambdaQueryWrapper<T>) queryWrapper;
                lw.select(BizEntity::getId);
                if(StrUtil.isNotBlank(lastId)){
                    lw.gt(BizEntity::getId, Long.parseLong(lastId));
                }
                lw.last("limit " + size);
                idList = list(lw).stream().map(BizEntity::getId).collect(Collectors.toList());
            }
            if(queryWrapper instanceof QueryWrapper){
                QueryWrapper<T> qw = (QueryWrapper<T>) queryWrapper;
                qw.select("id");
                if(StrUtil.isNotBlank(lastId)){
                    qw.gt("id", Long.parseLong(lastId));
                }
                qw.last("limit " + size);
                idList = list(qw).stream().map(BizEntity::getId).collect(Collectors.toList());
            }
            IPage<T> result = new Page<>();
            result.setRecords(Collections.emptyList());
            if(CollUtil.isNotEmpty(idList)){
                //根据id排序
                List<T> list = listByIds(idList).stream().sorted(Comparator.comparingLong(BizEntity::getId)).collect(Collectors.toList());
                result.setRecords(list);
            }
            result.setPages(0);
            result.setTotal(0);
            result.setCurrent(0);
            result.setSize(0);
            return (E) result;
        }
        return super.page(page, queryWrapper);
    }

    @Override
    public long count(Wrapper<T> queryWrapper) {
        return super.count(queryWrapper);
    }

    @Override
    public List<T> listByIds(Collection<? extends Serializable> idList) {
        LambdaQueryWrapper<T> queryWrapper = Wrappers.lambdaQuery(this.entityClass).in(T::getId, idList);
        return list(queryWrapper);
    }

    @Override
    public T get(T t) {
        return get(Wrappers.lambdaQuery(t));
    }

    @Override
    public boolean exists(T t) {
        return exists(Wrappers.lambdaQuery(t).select(BizEntity::getId));
    }

    @Override
    public boolean exists(Wrapper<T> queryWrapper) {
        if (queryWrapper instanceof LambdaQueryWrapper) {
            LambdaQueryWrapper<T> lw = (LambdaQueryWrapper<T>) queryWrapper;
            lw.select(BizEntity::getId);
            lw.last("limit 1");
        } else if (queryWrapper instanceof QueryWrapper ) {
            QueryWrapper<T> qw = (QueryWrapper<T>) queryWrapper;
            qw.select("id");
            qw.last("limit 1");
        }
        return getOne(queryWrapper, false) != null;
    }

    @Override
    public T get(Wrapper<T> queryWrapper) {
        if (queryWrapper instanceof LambdaQueryWrapper) {
            LambdaQueryWrapper<T> lw = (LambdaQueryWrapper<T>) queryWrapper;
            lw.last("limit 1");
        } else if (queryWrapper instanceof QueryWrapper ) {
            QueryWrapper<T> qw = (QueryWrapper<T>) queryWrapper;
            qw.last("limit 1");
        }
        return getOne(queryWrapper, false);
    }

    @Override
    public List<T> list(T t) {
        LambdaQueryWrapper<T> queryWrapper = Wrappers.lambdaQuery(t);
        return list(queryWrapper);
    }

    @Override
    public List<T> list() {
        LambdaQueryWrapper<T> queryWrapper = Wrappers.lambdaQuery(this.entityClass);
        return list(queryWrapper);
    }

    @Override
    public List<T> list(Wrapper<T> queryWrapper) {
        return super.list(queryWrapper);
    }

    @Override
    public <E extends IPage<T>> E page(E page) {
        return page(page, Wrappers.lambdaQuery(this.entityClass));
    }

    @Override
    public <E extends IPage<T>> E page(E page, T t) {
        return page(page, Wrappers.lambdaQuery(t));
    }

    @Override
    public List<T> getBySplitIds(String ids) {
        if (StrUtil.isBlank(ids)) {
            return null;
        }
        Set<Long> idSet = Stream.of(ids.split(",")).filter(StrUtil::isNotBlank).map(Long::valueOf).collect(Collectors.toSet());
        if (idSet.isEmpty()) {
            return null;
        }
        return listByIds(idSet);
    }

    @Override
    public T getById(Serializable id) {
        return get(Wrappers.lambdaQuery(this.entityClass).eq(BizEntity::getId, id));
    }
}
